package edu.tcc.iot.core.services.impl;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.log4j.Logger;

import edu.tcc.iot.core.mail.IMailFormat;
import edu.tcc.iot.core.mail.ProductLevelWarningMailFormat;
import edu.tcc.iot.core.mail.ProductValidateWarningMailFormat;
import edu.tcc.iot.core.services.IMailerService;
import edu.tcc.iot.domain.Product;
import edu.tcc.iot.domain.ProductInfo;
import edu.tcc.iot.domain.User;
import edu.tcc.iot.persistence.dao.IUserDAO;
import edu.tcc.iot.utils.ServiceLocator;

public class MailerService implements IMailerService{
	
	//Needs to be a singleton cause we cant open 1 connection 
	//to the email server each time we want to send a message
	private static MailerService INSTANCE = new MailerService();
	private final static Logger log = Logger.getLogger(MailerService.class);
	private IUserDAO userDAO = ServiceLocator.getInstance(IUserDAO.class);
	private Properties properties = new Properties();
	private Authenticator auth;
	private Session session;
	
	private MailerService(){
		initialize();
	}
	
	public static IMailerService getInstance() {
		return INSTANCE;
	}
	
	private void initialize() {
		try {
			properties.load(new FileInputStream("conf/mailer.properties"));
			auth = new Authenticator() {
				public PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication( 
							properties.getProperty("mail.email"), properties.getProperty("mail.password"));
				}
			};
			session = Session.getDefaultInstance(properties, auth);
			session.setDebug(true);
			//log.info("[CERS][ConnectionService] Mailer Service Initialized Successfully");
		} catch (FileNotFoundException e) {
			log.error("[CERS][ConnectionService] No properties to start mailer service was found");
		} catch (IOException e) {
			log.error("[CERS][ConnectionService] An error occurred while trying to start mailer service");
		}
	}

	private synchronized void sendEmail(IMailFormat format, String... args) {
		try {
			Message msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress(properties.getProperty("mail.email")));
			boolean first = true;
			for (User user : userDAO.getUsers()) {
				if (first) {
					msg.addRecipient(Message.RecipientType.TO, 
							new InternetAddress(user.getEmail(), user.getName())
							);
					first = false;
				} else {
					msg.addRecipient(Message.RecipientType.CC, 
							new InternetAddress(user.getEmail(), user.getName())
							);
				}
			}
			msg.setSubject(MessageFormat.format(format.getSubject(), args));
			MimeBodyPart textPart = new MimeBodyPart();
			textPart.setContent(MessageFormat.format(format.getBodyMail(), args), format.getTypeTextMail());
			Multipart mps = new MimeMultipart();
			mps.addBodyPart(textPart);
			msg.setContent(mps);
			Transport.send(msg);

		} catch (Exception e) {
			log.error("[CERS][ConnectionService] An error occurred while trying to send an email");
		}
	}

	@Override
	public void sendProductLevelWarningEmail(Product product) {
		ProductInfo productInfo = product.getProductInfo();
		IMailFormat format = new ProductLevelWarningMailFormat();
		sendEmail(format, productInfo.getName(), ""+productInfo.getQuantity());
		log.info("[CERS][ConnectionService] Product Level Warning Email sent successfully");
	}

	@Override
	public void sendProductValidateWarningEmail(Product product) {
		ProductInfo productInfo = product.getProductInfo();
		IMailFormat format = new ProductValidateWarningMailFormat();
		sendEmail(format, productInfo.getName(), productInfo.getValidate().toString());
		log.info("[CERS][ConnectionService] Product Validate Warning Email sent successfully");
	}
}
